home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / Source.bin / Firework.java < prev    next >
Text File  |  1998-10-08  |  13KB  |  420 lines

  1. package symantec.itools.multimedia;
  2.  
  3. import java.awt.Canvas;
  4. import java.awt.Graphics;
  5. import java.awt.Color;
  6. import java.awt.Dimension;
  7. import java.net.URL;
  8. import java.util.Random;
  9. import symantec.itools.lang.OS;
  10.  
  11. //    01/29/97    TWB    Integrated changes from Windows
  12. //    02/02/97    RKM    Fixed bug in unfreezeRockets, where freezing twice would not resume
  13. //  07/15/97    CAR marked fields transient as needed
  14. //  10/01/97    LAB    Removed unnecessary clipRect calls.  Now gets the graphics context each time
  15. //                the component is resized (Addresses Mac Bug #7832).
  16.  
  17. /**
  18.  * Firework component.  Creates an animated fireworks image.
  19.  * @version 1.0, Nov 26, 1996
  20.  * @author  Symantec
  21.  */
  22.  
  23. public class Firework
  24.     extends Canvas
  25.     implements Runnable
  26. {
  27.     /**
  28.      * Speed at which animation occurs.  Delay time = 100 / AnimationSpeed.
  29.      * Default value 10.
  30.      */
  31.     public int AnimationSpeed = 10;
  32.  
  33.     /**
  34.      * Chance of different rocket style. Rocket sytle changes if Math.random() * 100 < RocketStyleVariability.
  35.      * Default Value 10.
  36.      */
  37.     public int RocketStyleVariability = 10;
  38.  
  39.     /**
  40.      * Maximum number of rockets.
  41.      */
  42.     public int MaxRocketNumber = 9;
  43.     /**
  44.      * Controls "energy" of firwork explosion. Default value 850.
  45.      */
  46.     public int MaxRocketExplosionEnergy = 850;
  47.     /**
  48.      * Controls the density of the firework burst. Larger numbers give higher density.
  49.      * Default value 90.
  50.      */
  51.     public int MaxRocketPatchNumber = 90;
  52.     /**
  53.      * Controls the radius of the firework burst. Larger numbers give larger radius.
  54.      * Default value 68.
  55.      */
  56.     public int MaxRocketPatchLength = 68;
  57.  
  58.     /**
  59.      * Controls gravity of the firework simulation.
  60.      * Default value 400.
  61.      */
  62.     public int Gravity = 400;
  63.  
  64.     transient private Rocket rocket[];
  65.     transient private boolean rocketsCreated = false;
  66.     transient private Thread launcher = null;
  67.     transient private boolean suspend = false;
  68.  
  69.     /**
  70.      * Construct the defalut firework.
  71.      *
  72.      */
  73.  
  74.     public Firework() {
  75.         super();
  76.     }
  77.  
  78.     /**
  79.      * Tells this component that it has been added to a container.
  80.      * This is a standard Java AWT method which gets called by the AWT when
  81.      * this component is added to a container. Typically, it is used to
  82.      * create this component's peer.
  83.      *
  84.      * It has been overridden here to start the launcher thread.
  85.      *
  86.      * @see #removeNotify
  87.      */
  88.     public void addNotify() {
  89.         super.addNotify();
  90.         launcher = new Thread(this);
  91.         launcher.start();
  92.     }
  93.  
  94.     /**
  95.      * Tells this component that it is being removed from a container.
  96.      * This is a standard Java AWT method which gets called by the AWT when
  97.      * this component is removed from a container. Typically, it is used to
  98.      * destroy the peers of this component and all its subcomponents.
  99.      *
  100.      * It has been overridden here to stop the launcher thread.
  101.      *
  102.      * @see #addNotify
  103.      */
  104.     public synchronized void removeNotify() {
  105.         if (launcher != null) {
  106.             launcher.stop();
  107.             launcher = null;
  108.         }
  109.         super.removeNotify();
  110.     }
  111.  
  112.     /**
  113.      * Makes this component visible.
  114.      * This is a standard Java AWT method which gets called to show this
  115.      * component. If this component was invisible due to a previous hide()
  116.      * call it make this component visible again.
  117.      *
  118.      * @see #hide
  119.      */
  120.     public synchronized void show() {
  121.         super.show();
  122.         if (isVisible()) {
  123.             if (launcher != null)
  124.                 launcher.resume();
  125.         }
  126.     }
  127.  
  128.     /**
  129.      * Makes this component invisible.
  130.      * This is a standard Java AWT method which gets called to hide
  131.      * this component. A hidden component cannot be seen by the user nor
  132.      * does it take up space in its container, but it does continue to
  133.      * exist.
  134.      *
  135.      * @see #show
  136.      */
  137.     public synchronized void hide() {
  138.         super.hide();
  139.         if (!isVisible()) {
  140.             if (launcher != null)
  141.                 suspend = true;
  142.         }
  143.     }
  144.  
  145.  
  146.     void createRockets() {
  147.         rocketsCreated = true;
  148.  
  149.         Rocket tempRocket[] = new Rocket[MaxRocketNumber];
  150.  
  151.         Dimension dim = size();
  152.  
  153.         for (int i = 0; i < MaxRocketNumber; i++)
  154.             tempRocket[i] = new Rocket(dim.width, dim.height, Gravity);
  155.  
  156.         rocket = tempRocket;
  157.     }
  158.  
  159.     /**
  160.      * Moves and/or resizes this component.
  161.      * This is a standard Java AWT method which gets called to move and/or
  162.      * resize this component. Components that are in containers with layout
  163.      * managers should not call this method, but rely on the layout manager
  164.      * instead.
  165.      *
  166.      * @param x horizontal position in the parent's coordinate space
  167.      * @param y vertical position in the parent's coordinate space
  168.      * @param width the new width
  169.      * @param height the new height
  170.      */
  171.     public synchronized void reshape(int x, int y, int width, int height) {
  172.         super.reshape(x, y, width, height);
  173.         rocketsCreated = false;
  174.     }
  175.  
  176.     /**
  177.      * Firework thread body.  This method is called by the Java virtual
  178.      * machine is response to the program's call to the start method of
  179.      * this thread.
  180.      */
  181.     public void run() {
  182.         int i,
  183.  
  184.         e = (int)(Math.random() * MaxRocketExplosionEnergy * 3 / 4) +
  185.             MaxRocketExplosionEnergy / 4 + 1,
  186.         p = (int)(Math.random() * MaxRocketPatchNumber * 3 / 4) +
  187.             MaxRocketPatchNumber / 4 + 1,
  188.         l = (int)(Math.random() * MaxRocketPatchLength * 3 / 4) +
  189.             MaxRocketPatchLength / 4 + 1;
  190.  
  191.         long s = (long)(Math.random() * 10000);
  192.         boolean sleep;
  193.         Graphics g = null;
  194.  
  195.         while (true) {
  196.             if (g == null)
  197.                 g = getGraphics();
  198.  
  199.             if (suspend) {
  200.                 suspend = false;
  201.                 launcher.suspend();
  202.             }
  203.  
  204.             if (!rocketsCreated)
  205.             {
  206.                 g = getGraphics();
  207.                 createRockets();
  208.             }
  209.  
  210.             if (rocketsCreated && g != null) {
  211.                 Dimension dim = size();
  212.  
  213.                 try {
  214.                     Thread.sleep(100 / AnimationSpeed);
  215.                 } catch(InterruptedException x) {
  216.                 }
  217.  
  218.                 sleep = true;
  219.  
  220.                 for (i = 0; i < MaxRocketNumber; i++)
  221.                     sleep = sleep && rocket[i].sleep;
  222.  
  223.                 if (sleep && Math.random() * 100 < RocketStyleVariability) {
  224.                     e = (int)(Math.random() * MaxRocketExplosionEnergy * 3 / 4) +
  225.                         MaxRocketExplosionEnergy / 4 + 1;
  226.                     p = (int)(Math.random() * MaxRocketPatchNumber * 3 / 4) +
  227.                         MaxRocketPatchNumber / 4 + 1;
  228.                     l = (int)(Math.random() * MaxRocketPatchLength * 3 / 4) +
  229.                         MaxRocketPatchLength / 4 + 1;
  230.                     s = (long)(Math.random() * 10000);
  231.                 }
  232.  
  233.                 for (i = 0; i < MaxRocketNumber; ++i) {
  234.                     Rocket r = rocket[i];
  235.                     if (r.sleep && Math.random() * MaxRocketNumber * l < 1) {
  236.                         r.init(e, p, l, s);
  237.                         r.start();
  238.                     }
  239.  
  240.                     if (rocketsCreated)
  241.                         r.show(g);
  242.                 }
  243.             }
  244.         }
  245.     }
  246.  
  247.     /**
  248.      * Suspend the firework animation.
  249.      */
  250.     public void freezeRockets() {
  251.         suspend = true;
  252.     }
  253.  
  254.     /**
  255.      * Resume the firework animation.
  256.      */
  257.     public void unfreezeRockets() {
  258.         //Set suspend to false, in case freezeRockets was called after it was suspended
  259.         suspend = false;
  260.         launcher.resume();
  261.     }
  262.  
  263.     /**
  264.      * Paints a black background for this firework.
  265.      * This is a standard Java AWT method which typically gets called
  266.      * by the AWT to handle painting this component. It paints this component
  267.      * using the given graphics context. The graphics context clipping region
  268.      * is set to the bounding rectangle of this component and its <0,0>
  269.      * coordinate is this component's top-left corner.
  270.      *
  271.      * @param g the graphics context used for painting
  272.      * @see java.awt.Component#repaint
  273.      * @see java.awt.Component#update
  274.      */
  275.     public void paint(Graphics g) {
  276.         Dimension dim = size();
  277.         g.setColor(Color.black);
  278.         g.fillRect(0, 0, dim.width + 1, dim.height + 1);
  279.     }
  280. }
  281.  
  282.  
  283. class Rocket {
  284.     public boolean sleep = true;
  285.  
  286.     private int energy,patch,length,
  287.              mx,my,
  288.              gravity,
  289.              ox,oy,
  290.              vx[],vy[],
  291.              x,y,
  292.              red,blue,green,
  293.              t;
  294.     private Random random;
  295.  
  296.     public Rocket(int a, int b, int g) {
  297.         mx = a;
  298.         my = b;
  299.         gravity = g;
  300.     }
  301.  
  302.     public void init(int e, int p, int l, long seed) {
  303.         int i;
  304.  
  305.         energy = e;
  306.         patch = p;
  307.         length = l;
  308.  
  309.         random = new Random(seed);
  310.  
  311.         vx = new int[patch];
  312.         vy = new int[patch];
  313.  
  314.         if (!System.getProperty("os.name").equals("Windows 95")) {
  315.             red = (int)(random.nextDouble() * 128) + 128;
  316.             blue = (int)(random.nextDouble() * 128) + 128;
  317.             green = (int)(random.nextDouble() * 128) + 128;
  318.         }
  319.         else {
  320.             int add = 0;
  321.             double d = 0.0;
  322.             
  323.             d = random.nextDouble();
  324.             if (d >= 0.0 && d <= .2) add = 0;
  325.             if (d > .2 && d <= .4) add = 32;
  326.             if (d > .4 && d <= .6) add = 64;
  327.             if (d > .6 && d <= .8) add = 96;
  328.             if (d > .8 && d <= 1.0) add = 128;
  329.             red = add + 128;
  330.             d = random.nextDouble();
  331.             if (d >= 0.0 && d <= .2) add = 0;
  332.             if (d > .2 && d <= .4) add = 32;
  333.             if (d > .4 && d <= .6) add = 64;
  334.             if (d > .6 && d <= .8) add = 96;
  335.             if (d > .8 && d <= 1.0) add = 128;
  336.             blue = add + 128;
  337.             d = random.nextDouble();
  338.             if (d >= 0.0 && d <= .2) add = 0;
  339.             if (d > .2 && d <= .4) add = 32;
  340.             if (d > .4 && d <= .6) add = 64;
  341.             if (d > .6 && d <= .8) add = 96;
  342.             if (d > .8 && d <= 1.0) add = 128;
  343.             green = add + 128;
  344.         }
  345.  
  346.         ox = (int)(Math.random()*mx/2)+mx/4;
  347.         oy = (int)(Math.random()*my/2)+my/4;
  348.  
  349.         for(i = 0; i < patch; ++i) {
  350.             vx[i] = (int)(Math.random() * energy) - energy / 2;
  351.             vy[i] = (int)(Math.random() * energy * 7 / 8) - energy / 8;
  352.         }
  353.     }
  354.  
  355.     public void start() {
  356.         t = 0;
  357.         sleep = false;
  358.     }
  359.  
  360.     public void show(Graphics g) {
  361.         if (!sleep) {
  362.             if (t < length) {
  363.                 int i, cr, cg, cb;
  364.                 double s;
  365.                 Color color;
  366.  
  367.                 if (!System.getProperty("os.name").equals("Windows 95")) {
  368.                     cr = (int)(random.nextDouble() * 64) - 32 + red;
  369.                     cg = (int)(random.nextDouble() * 64) - 32 + green;
  370.                     cb = (int)(random.nextDouble() * 64) - 32 + blue;
  371.                 }
  372.                 else {
  373.                     cr = (random.nextDouble() < 0.50 ? -32 : 32) + red;
  374.                     cg = (random.nextDouble() < 0.50 ? -32 : 32) + green;
  375.                     cb = (random.nextDouble() < 0.50 ? -32 : 32) + blue;
  376.                 }
  377.                 if (cr >= 0 && cr <= 256)
  378.                     red = cr;
  379.                 if (cg >= 0 && cg <= 256)
  380.                     green = cg;
  381.                 if (cb >= 0 && cb <= 256)
  382.                     blue = cb;
  383.  
  384.                 int _red = red == 256 ? 255 : red;
  385.                 int _green = green == 256 ? 255 : green;
  386.                 int _blue = blue == 256 ? 255 : blue;
  387.                 color = new Color(_red, _green, _blue);
  388.  
  389.                 g.setColor(color);
  390.                 for (i = 0; i < patch; ++i) {
  391.                     s = (double)t / 100;
  392.                     x = (int)(vx[i] * s);
  393.                     y = (int)(vy[i] * s - gravity * s * s);
  394.  
  395.                     g.drawLine(ox + x, oy - y, ox + x, oy - y);
  396.                 }
  397.                 g.setColor(Color.black);
  398.                 for (i = 0; i < patch; ++i) {
  399.                     if (t >= length / 2) {
  400.                         for (int j = 0; j < 2; ++j)
  401.                         {
  402.                             s = (double)((t - length / 2) * 2 + j) / 100;
  403.                             x = (int)(vx[i] * s);
  404.                             y = (int)(vy[i] * s - gravity * s * s);
  405.  
  406.                             g.drawLine(ox + x, oy - y, ox + x, oy - y);
  407.                         }
  408.                     }
  409.                 }
  410.  
  411.                 ++t;
  412.  
  413.             } else
  414.                 sleep = true;
  415.  
  416.         }
  417.     }
  418. }
  419.  
  420.